/*
 * Copyright (C) 2015-2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include "PlanetWars2dRT-core/specific/controller/player_robots.h"
#include "PlanetWars2dRT-core/specific/model/ship_position.h"
#include "PlanetWars2dRT-core/specific/model/ships.h"
#include "PlanetWars2dRT-core/specific/model/planet_position.h"
#include "PlanetWars2dRT-core/specific/model/planet_size.h"
#include "PlanetWars2dRT-core/specific/model/planets.h"
#include "PlanetWars2dRT-core/specific/model/game_players.h"
#include "PlanetWars2dRT-core/specific/model/player_playing_functions.h"
#include "PlanetWars2dRT-core/specific/controller/player_robots_utils.h"


EXTERN_C_BEGIN


void
player_robot_very_stupid_rusher_act(struct game_t*   a_game,
				    struct player_t* a_player)
{
  unsigned char player_index = player_data_set_as_player_index(a_game,
							       a_player);
  
  for(size_t i=0; i < universe_get_nb_planets(&a_game->universe); ++i)
    {
      const planet_t* planet_i =
	universe_get_const_planet_no_check(&a_game->universe, i);
      if(planet_i->player_index != player_index)
	{
	  const position_2d_uint position_to_attack =
	    planet_get_center_position(planet_i);
	  universe_ships_of_player_index_go_to(&a_game->universe,
					       player_index,
					       &position_to_attack);
	  return;
	}
    }
}

void
player_robot_stupid_rusher_act(struct game_t*   a_game,
			       struct player_t* a_player)
{
  unsigned char player_index = player_data_set_as_player_index(a_game,
							       a_player);
  
  const position_2d_uint pos_center_my_planets =
    universe_get_center_position_of_planets_of_player_index(&a_game->universe,
							    player_index);
  
  size_t other_planets_nb;
  const planet_t** other_planets;
  other_planets = universe_get_planets_not_of_player_index(&a_game->universe,
							   player_index,
							   &other_planets_nb);
  if(other_planets != NULL)
    {
      position_2d_uint position_to_attack;
      
      position_to_attack = planet_get_center_position(other_planets[0]);
      for(size_t i=1; i < other_planets_nb; ++i)
	{
	  const position_2d_uint position_center =
	    planet_get_center_position(other_planets[i]);
	  if(distance_between_2_positions_2d_uint(&position_center,
						  &pos_center_my_planets)
	     <
	     distance_between_2_positions_2d_uint(&pos_center_my_planets,
						  &position_to_attack))
	    {
	      position_to_attack = position_center;
	    }
	}
      free(other_planets);
      
      universe_ships_of_player_index_go_to(&a_game->universe,
					   player_index,
					   &position_to_attack);
    }
}

void
player_robot_easy(struct game_t*   a_game,
		  struct player_t* a_player)
{
  unsigned char player_index = player_data_set_as_player_index(a_game,
							       a_player);
  
  const position_2d_uint position_center_my_planets =
    universe_get_center_position_of_planets_of_player_index(&a_game->universe,
							    player_index);
  
  size_t other_planets_nb;
  const planet_t** other_planets;
  other_planets = universe_get_planets_not_of_player_index(&a_game->universe,
							   player_index,
							   &other_planets_nb);
  if(other_planets != NULL)
    {
      position_2d_uint position_to_attack =
	planet_get_center_position(other_planets[0]);
      size_t planet_to_attack_index = 0;
      
      for(size_t i=1; i < other_planets_nb; ++i)
	{
	  const position_2d_uint position_center =
	    planet_get_center_position(other_planets[i]);
	  if(distance_between_2_positions_2d_uint(&position_center,
						  &position_center_my_planets)
	     <
	     distance_between_2_positions_2d_uint(&position_center_my_planets,
						  &position_to_attack))
	    {
	      position_to_attack = position_center;
	      planet_to_attack_index = i;
	    }
	}
      const planet_t* planet_to_attack = other_planets[planet_to_attack_index];
      free(other_planets);
      
      if(is_possible_to_attack_planet_for_player(a_game,
						 player_index,
						 planet_to_attack))
	{
	  universe_ships_of_player_index_go_to(&a_game->universe,
					       player_index,
					       &position_to_attack);
	}
    }
}

void
player_robot_normal(struct game_t*   a_game,
		    struct player_t* a_player)
{
  unsigned char player_index = player_data_set_as_player_index(a_game,
							       a_player);
  
  const position_2d_uint position_center_my_planets =
    universe_get_center_position_of_planets_of_player_index(&a_game->universe,
							    player_index);
  
  size_t other_planets_nb;
  const planet_t** other_planets =
    universe_get_planets_not_of_player_index(&a_game->universe,
					     player_index,
					     &other_planets_nb);
  
  if(other_planets != NULL)
    {
      position_2d_uint position_to_attack =
	planet_get_center_position(other_planets[0]);
      size_t planet_to_attack_index = 0;
      
      for(size_t i=1; i < other_planets_nb; ++i)
	{
	  const position_2d_uint position_center =
	    planet_get_center_position(other_planets[i]);
	  if(distance_between_2_positions_2d_uint(&position_center,
						  &position_center_my_planets)
	     <
	     distance_between_2_positions_2d_uint(&position_center_my_planets,
						  &position_to_attack))
	    {
	      position_to_attack = position_center;
	      planet_to_attack_index = i;
	    }
	}
      const planet_t* planet_to_attack = other_planets[planet_to_attack_index];
      
      if(is_possible_to_attack_planet_for_player(a_game,
						 player_index,
						 planet_to_attack))
	{
	  universe_ships_of_player_index_go_to(&a_game->universe,
					       player_index,
					       &position_to_attack);
	}
      else /* the second closest planet is tried */
	{
	  position_2d_uint position_to_attack2 =
	    planet_get_center_position(other_planets[0]);
	  size_t planet_to_attack_index2 = 0;
	  
	  for(size_t i=1; i < other_planets_nb; ++i)
	    {
	      const position_2d_uint position_center =
		planet_get_center_position(other_planets[i]);
	      if((distance_between_2_positions_2d_uint(&position_center,
						       &position_center_my_planets)
		  <
		  distance_between_2_positions_2d_uint(&position_center_my_planets,
						       &position_to_attack2))
		 && i != planet_to_attack_index)
		{
		  position_to_attack2 = position_center;
		  planet_to_attack_index2 = i;
		}
	    }
	  const planet_t* planet_to_attack =
	    other_planets[planet_to_attack_index2];
	  
	  if(is_possible_to_attack_planet_for_player(a_game,
						     player_index,
						     planet_to_attack))
	    {
	      universe_ships_of_player_index_go_to(&a_game->universe,
						   player_index,
						   &position_to_attack2);
	    }
	}
      
      size_t AI_planets_nb;
      const planet_t** AI_planets =
	universe_get_planets_of_player_index(&a_game->universe,
					     player_index,
					     &AI_planets_nb);
      if(AI_planets != NULL)
	{
	  /* we defend our planets if they are attacked */
	  for(size_t i=0; i < AI_planets_nb; ++i)
	    {
	      const position_2d_uint position_center =
		planet_get_center_position(AI_planets[i]);
	      unsigned int enemy_ships_around_planet_to_check = 0;
	      const unsigned int max_distance_for_a_ship_to_attack =
		2 * planet_get_radius(planet_to_attack);
	      
	      for(size_t j=0; j < universe_get_nb_ships(&a_game->universe); ++j)
		{
		  const ship_t* ship_j =
		    universe_get_const_ship_no_check(&a_game->universe, j);
		  const position_2d_uint ship_position =
		    ship_get_center_position_current(ship_j);
		  
		  if(ship_get_player_index(ship_j) != player_index
		     &&
		     distance_between_2_positions_2d_uint(&ship_position,
							  &position_center)
		     < max_distance_for_a_ship_to_attack * 2
		     &&
		     (ship_get_top_left_position_to_go_x(ship_j) - position_center.x)
		     < max_distance_for_a_ship_to_attack
		     &&
		     (ship_get_top_left_position_to_go_y(ship_j) - position_center.y)
		     < max_distance_for_a_ship_to_attack)
		    {
		      ++enemy_ships_around_planet_to_check;
		    }
		}
	  
	      if(enemy_ships_around_planet_to_check > 5)
		{
		  size_t nb_ships;
		  ship_t** ships =
		    universe_get_ships_of_player_index(&a_game->universe,
						       player_index,
						       &nb_ships);
		  if(ships != NULL)
		    {
		      const size_t nb_ships_to_move = (3 * nb_ships) / 4;
		      for(size_t j = 0; j < nb_ships_to_move; ++j)
			{
			  ship_t* ship_j = ships[j];
			  const position_2d_uint ship_j_position =
			    ship_get_center_position_current(ship_j);
			  
			  if(distance_between_2_positions_2d_uint(&ship_j_position,
								  &position_center)
			     < max_distance_for_a_ship_to_attack * 2)
			    {
			      ship_set_top_left_position_to_go(ship_j,
							       &position_center);
			    }
			}
		      free(ships);
		    }
		}
	    }
	  free(AI_planets);
	}
      free(other_planets);
    }
}


EXTERN_C_END
